#pragma once

#include "sfc/collections.h"
#include "sfc/sync.h"

namespace sfc::cyber {

template <class T>
class MsgQueue {
  CircBuf<T> _buf;
  sync::Mutex _mutex{};
  sync::Condvar _condvar{};

 public:
  explicit MsgQueue(usize capacity) : _buf{_buf.with_capacity(capacity)} {}

  ~MsgQueue() {}

  auto pop() -> Option<T> {
    auto lock = _mutex.lock();
    if (_buf.is_empty()) {
      return {};
    }

    auto res = _buf.pop_front();
    return res;
  }

  auto push(T msg, u32 try_ms) -> bool {
    auto lock = _mutex.lock();
    if (_buf.is_full()) {
      _condvar.wait_timeout_ms(lock, try_ms);
    }

    const auto res = !_buf.is_full();
    _buf.push_back(static_cast<T&&>(msg));
    return res;
  }
};

}  // namespace sfc::cyber
